<?php

namespace App\Admin;

use App\Library\Logic\UploadFileLogic;
use getID3;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\UploadedFile;
use Intervention\Image\Drivers\Gd\Driver;
use Intervention\Image\ImageManager;
use OSS\Core\OssException;
use OSS\Http\RequestCore_Exception;
use OSS\OssClient;

class AdminUpload
{
    /**
     * 上传文件
     * @param UploadedFile $file
     * @return Model
     * @throws OssException
     * @throws RequestCore_Exception
     */
    public static function upload(UploadedFile $file): Model
    {
        $data = [
            'serialNumber' => UploadFileLogic::getSerialNumber(),
            'fileName' => $file->getFilename(),
            'filePath' => $file->getRealPath(),
            'originalName' => $file->getClientOriginalName(),
            'fileSize' => $file->getSize(),
            'fileExt' => $file->getClientOriginalExtension(),
            'mimeType' => $file->getMimeType(),
        ];

        $data['url'] = fileIdToUrl($data['serialNumber']);
        $data = self::getID3($data);
        $data = self::executeImg($data);
        $oss = config('oss');
        $ossClient = new OssClient($oss['key'], $oss['secret'], $oss['endpoint']);
        $data['ossInfo'] = $ossClient->putObject(
            $oss['bucket'],
            substr(str_replace($oss['url'], '/', $data['url']), 1),
            file_get_contents($file->getRealPath()),
            ['Content-Type' => $file->getMimeType()]
        );
        $model = UploadFileLogic::insertForModel($data);
        cache(['uploadFile:' . $model->serial_number => $model->mime_type]);
        return $model;
    }

    /**
     * 复制文件
     * @param string $serialNumber
     * @return Model|null
     * @throws OssException
     * @throws RequestCore_Exception
     */
    public static function copy(string $serialNumber): ?Model
    {
        $uploadFile = UploadFileLogic::findBySerialNumber($serialNumber);
        if (is_null($uploadFile)) return null;
        self::unsetUploadFile($uploadFile);
        $model = UploadFileLogic::insertForModel($uploadFile->toArray());
        $oss = config('oss');
        $ossClient = new OssClient($oss['key'], $oss['secret'], $oss['endpoint']);
        $model->oss_info = $ossClient->copyObject(
            $oss['bucket'],
            fileIdToDir($serialNumber),
            $oss['bucket'],
            fileIdToDir($model->serial_number)
        );
        $model->url = fileIdToUrl($model->serial_number);
        $model->save();
        return $model;
    }

    /**
     * getID3
     * @param array $data
     * @return array
     */
    private static function getID3(array $data): array
    {
        if (!in_array($data['mimeType'], array_merge(__('mime_type.audio'), __('mime_type.video')))) return $data;
        $getID3 = new getID3;
        $fileInfo = $getID3->analyze($data['filePath']);
        $data['encoding'] = $fileInfo['encoding'];
        $data['playtimeSeconds'] = $fileInfo['playtime_seconds'];
        $data['bitrate'] = $fileInfo['bitrate'];
        $data['playtimeString'] = $fileInfo['playtime_string'];
        if (in_array($data['mimeType'], __('mime_type.video'))) {
            $data['img_width'] = $fileInfo['video']['resolution_x'] ?? 0;
            $data['img_height'] = $fileInfo['video']['resolution_y'] ?? 0;
        }
        return $data;
    }

    /**
     * executeImg
     * @param array $data
     * @return array
     */
    private static function executeImg(array $data): array
    {
        if (!in_array($data['mimeType'], __('mime_type.img'))) return $data;
        $manager = new ImageManager(new Driver);
        $image = $manager->read($data['filePath']);
        $data['imgWidth'] = $image->width() ?? 0;
        $data['imgHeight'] = $image->height() ?? 0;
        return $data;
    }

    /**
     * unsetUploadFile
     * @param Model $uploadFile
     * @return void
     */
    private static function unsetUploadFile(Model $uploadFile): void
    {
        unsetObject($uploadFile, [
            'id',
            'serial_number',
            'oss_info',
            'url',
            'created_at',
            'updated_at',
        ]);
    }
}
